package net.wanho.shop.service.impl;

import lombok.RequiredArgsConstructor;
import net.wanho.shop.common.UserConstant;
import net.wanho.shop.exception.RoleExistsException;
import net.wanho.shop.mapper.PermissionMapper;
import net.wanho.shop.mapper.RoleMapper;
import net.wanho.shop.po.Permission;
import net.wanho.shop.po.Role;
import net.wanho.shop.service.RoleService;
import net.wanho.shop.vo.PermVo;
import net.wanho.shop.vo.RoleAddVo;
import net.wanho.shop.vo.RoleFatherVo;
import net.wanho.shop.vo.RoleSonVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author 猛虎王
 * @since 2024-12-24
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class RoleServiceImpl implements RoleService {

    private final RoleMapper roleMapper;
    private final PermissionMapper permissionMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 角色表分页查询
     *
     * @param pageNum
     * @param pageSize
     * @param role
     * @return
     */
//    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
//    @Override
//    public PageInfo findPage(int pageNum, int pageSize, Role role) {
//        if (ObjectUtil.isNull(role)) {
//            role = new Role();
//        }
//
//        // 分页
//        PageHelper.startPage(pageNum, pageSize);
//        List<Role> roleList = roleMapper.select(role);
//        return new PageInfo(roleList);
//    }

    /**
     * 根据主键查询角色表
     *
     * @param roleId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    @Override
    public Role findById(Serializable roleId) {
        return roleMapper.selectById(roleId);
    }

    /**
     * 角色表新增
     *
     * @param role
     */
    @Override
    public void add(Role role) {
        roleMapper.insert(role);
    }

    /**
     * 修改角色表
     *
     * @param role
     */
    @Override
    public void modify(Role role) {
        roleMapper.update(role);
    }

    /**
     * 根据主键删除角色表
     *
     * @param roleId
     */
    @Override
    public void removeById(Serializable roleId) {
        if (((String) roleId).contains(",")) {
            roleMapper.deleteByIds(((String) roleId).split(","));
        } else {
            roleMapper.deleteById(roleId);
        }
    }

    /**
     * 角色表新增
     */
    @Override
    public void addRole(RoleAddVo roleAddVo) {
        // 判断角色名是否为空 不能为空
        if (roleAddVo.getRoleName() == null) {
            throw new RoleExistsException("角色名不能为空");
        }

        // 获取角色
        Role role = roleMapper.selectByRoleName(roleAddVo.getRoleName());
        // 判断角色是否存在 存在抛出异常
        if (role != null) {
            throw new RoleExistsException("角色名已存在");
        }
        // 封装角色
        Role role1 = new Role();
        role1.setRoleName(roleAddVo.getRoleName());
        role1.setRoleDesc(roleAddVo.getRoleDesc());

        // 插入角色
        roleMapper.insert(role1);


    }

    @Override
    public List<RoleFatherVo> findRoles() {
        // 获取所有的角色
        List<Role> roles = roleMapper.select(new Role());
        return roles.stream().map(role -> {
            // 遍历每个角色并创建RoleFatherVo对象
            RoleFatherVo roleFatherVo = new RoleFatherVo();
            //给每个RoleFather属性赋值
            roleFatherVo.setRoleId(role.getRoleId());
            roleFatherVo.setRoleName(role.getRoleName());
            roleFatherVo.setRoleDesc(role.getRoleDesc());
            //获取每个角色的权限字符串并按照，分割为数组
            String[] pidArr = role.getPsIds().split(",");
            //通过pid数组批量查询给角色的所有权限
            List<Permission> permissionList = permissionMapper.selectBatch(pidArr);
            //遍历所有权限，过滤出所有一级权限并查出子权限，生成该角色所拥有的权限树
            List<RoleSonVo> roleSonVos = permissionList.stream().filter(item -> item.getPsLevel() == 1)
                    .map(item -> {
                        RoleSonVo wrapper = wrapper(item);
                        findChildren(wrapper, permissionList);
                        return wrapper;
                    }).toList();
            // 将过滤后的权限树赋值给RoleFatherVo中的属性Children
            roleFatherVo.setChildren(roleSonVos);
            //返回RoleFather对象，收集成集合返回
            return roleFatherVo;
        }).toList();
    }

    // 递归查询子菜单
    private void findChildren(RoleSonVo item, List<Permission> list) {
        List<RoleSonVo> children = list.stream()
                .filter(subItem -> subItem.getPsPid().equals(item.getId()))
                .map(subItem -> {
                    RoleSonVo wrapper = wrapper(subItem);
                    findChildren(wrapper, list);
                    return wrapper;
                }).toList();
        item.setChildren(children);
    }

    // 转换 Permission 为 RoleSonVo
    private RoleSonVo wrapper(Permission permission) {
        RoleSonVo roleSonVo = new RoleSonVo();
        roleSonVo.setId(permission.getPsId());
        roleSonVo.setAuthName(permission.getPsName());
        roleSonVo.setPath(permission.getPsApiPath());
        roleSonVo.setLevel(permission.getPsLevel());
        return roleSonVo;
    }

    @Override
    public List<Role> findAll() {
        return roleMapper.selectAll();
    }

    @Override
    public List<PermVo> removePermissionsByRoleId(Integer rightId, Integer roleId) {
        // 获取要删除的权限和子权限
        List<Integer> deletedRightsIds = new ArrayList<>();
        deletedRightsIds.add(rightId);
        findPermission(deletedRightsIds, rightId);

        // 获取当前角色所有权限
        String[] allRights = roleMapper.selectById(roleId).getPsIds().split(",");


        // 计算删除后的权限
        String ids = Arrays.stream(allRights)
                .filter(item -> !deletedRightsIds.contains(Integer.parseInt(item)))
                .collect(Collectors.joining(","));

        // 更新权限
        roleMapper.updatePermissions(roleId, ids);

        // 删除Redis中所有用户的菜单数据
        Set<String> keys = redisTemplate.keys(UserConstant.MENU_PREFIX + "*");
        assert keys != null;
        redisTemplate.delete(keys);

        // 获取角色下最新列表
        List<Permission> perms = permissionMapper.selectBatch(ids.split(","));
        List<PermVo> list = perms.stream()
                .filter(item -> item.getPsPid() == 0)
                .map(item -> {
                    // 转换Permission为PermVo
                    PermVo permVo = wrapperPer(item);
                    // 递归查询子权限
                    findChildrenDel(permVo, perms);
                    return permVo;
                }).collect(Collectors.toList());

        return list;
    }

    @Override
    public void addPermissionsByRoleId(Integer roleId, Map<String, String> ids) {
        // 获取要添加的权限和子权限
        String rids = ids.get("rids");

        // 更新权限
        roleMapper.updatePermissions(roleId, rids);

        // 删除Redis中所有用户的菜单数据
        Set<String> keys = redisTemplate.keys(UserConstant.MENU_PREFIX + "*");
        assert keys != null;
        redisTemplate.delete(keys);

        // 获取角色下最新列表
        List<Permission> perms = permissionMapper.selectBatch(ids.get("rids").split(","));
        List<PermVo> list = perms.stream()
                .filter(item -> item.getPsPid() == 0)
                .map(item -> {
                    // 转换Permission为PermVo
                    PermVo permVo = wrapperPer(item);
                    // 递归查询子权限
                    findChildrenDel(permVo, perms);
                    return permVo;
                }).toList();

    }

    @Override
    public void modifyByRoleId(Role role, Integer roleId) {
        Role role1 = roleMapper.selectById(roleId);

        if (role1 == null)
            throw new RuntimeException("角色不存在");

        roleMapper.update(role);
    }


    private void findChildrenDel(PermVo item, List<Permission> perms) {
        List<PermVo> children = perms.stream()
                .filter(subItem -> subItem.getPsPid().equals(item.getId()))
                .map(subItem -> {
                    PermVo permVo = wrapperPer(subItem);
                    findChildrenDel(permVo, perms);
                    return permVo;
                }).collect(Collectors.toList());
        item.setChildren(children);
    }

    private PermVo wrapperPer(Permission item) {
        PermVo permVo = new PermVo();
        permVo.setId(item.getPsId());
        permVo.setAuthName(item.getPsName());
        permVo.setPath(item.getPsApiPath());
        return permVo;
    }

    // 递归查找子权限
    private void findPermission(List<Integer> deletedRightsIds, Integer rightId) {
        List<Permission> perms = permissionMapper.selectChildrenByPid(rightId);
        perms.forEach(item -> {
            deletedRightsIds.add(item.getPsId());
            // 递归
            findPermission(deletedRightsIds, item.getPsId());
        });

    }

}
